package com.csaba.swing.gui;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.net.URL;
import java.util.List;

import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;

import com.csaba.connector.model.Account;
import com.csaba.connector.model.Amount;
import com.csaba.connector.model.Customer;
import com.csaba.connector.model.Session;
import com.csaba.swing.MainWindow;
import com.csaba.swing.action.AccountOverviewAction;
import com.csaba.swing.action.ActionFactory;
import com.csaba.swing.gui.util.DynamicColumnLayout;
import com.csaba.swing.gui.util.TableSizeContainer;
import com.csaba.swing.gui.util.WindowSizeContanier;

@SuppressWarnings( "serial" )
public class AccountListView extends JInternalFrame implements ContextListener
{
	private static String[] HEADERS = new String[] {
			MainWindow.getString("AccountListView.header.bank"), MainWindow.getString("AccountListView.header.number"), MainWindow.getString("AccountListView.header.name"), MainWindow.getString("AccountListView.header.type"), MainWindow.getString("AccountListView.header.currency"), MainWindow.getString("AccountListView.header.bookBalance"), //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
			MainWindow.getString("AccountListView.header.availBalance"), }; //$NON-NLS-1$
	private static Class<?>[] COLUMN_CLASS = new Class<?>[] { ImageIcon.class, String.class, String.class,
			String.class, String.class, Amount.class, Amount.class, };

	JLabel bank;
	JLabel customerName;
	JTable accounts;
	JLabel allAvailable;
	JLabel allBook;
	Customer customer;
	Account[] accountsList;

	public AccountListView()
	{
		super(MainWindow.getString("AccountListView.title"), true, true, true, true); //$NON-NLS-1$
		setDefaultCloseOperation(JInternalFrame.DISPOSE_ON_CLOSE);
		if ( !WindowSizeContanier.getInstance().monitorComponent(this) )
			setSize(600, 350);
		setFrameIcon(GUIContext.getIcon("accounts", 16)); //$NON-NLS-1$

		//init layout
		final JPanel general = new JPanel(new DynamicColumnLayout(new int[] { DynamicColumnLayout.RIGHT,
				DynamicColumnLayout.LEFT }));
		general.add(new JLabel(MainWindow.getString("AccountListView.bank"))); //$NON-NLS-1$
		general.add(bank = new JLabel("")); //$NON-NLS-1$
		general.add(new JLabel(MainWindow.getString("AccountListView.customer"))); //$NON-NLS-1$
		general.add(customerName = new JLabel("")); //$NON-NLS-1$

		final JPanel buttons = new JPanel();
		final JButton ok = new JButton(new AbstractAction(MainWindow.getString("AccountListView.button.close")) //$NON-NLS-1$
				{

					@Override
					public void actionPerformed( final ActionEvent arg0 )
					{
						dispose();
					}

				});
		buttons.add(ok);

		final JPanel data = new JPanel(new BorderLayout());

		accounts = new JTable(new AccountListModel());
		accounts.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

		accounts.addMouseListener(new MouseAdapter()
		{
			@Override
			public void mouseClicked( final MouseEvent e )
			{
				if ( e.getClickCount() > 1 )
				{//handle as double click
					final int index = accounts.getSelectedRow();
					final Account account = ( (AccountListModel) accounts.getModel() ).getAccountAt(index);
					final AccountView view = new AccountView();
					MainWindow.getDesktop().add(view);
					view.showIt(account);
				}

			}

		});
		final JScrollPane scrollPane = new JScrollPane(accounts);
		accounts.setFillsViewportHeight(true);
		data.add(scrollPane, BorderLayout.CENTER);
		final DefaultTableCellRenderer amountRenderer = new DefaultTableCellRenderer();
		amountRenderer.setHorizontalAlignment(SwingConstants.RIGHT);
		accounts.setDefaultRenderer(Amount.class, amountRenderer);

		final JPanel summary = new JPanel(new DynamicColumnLayout(new int[] { DynamicColumnLayout.RIGHT,
				DynamicColumnLayout.LEFT }));
		summary.add(new JLabel(MainWindow.getString("AccountListView.totalBook"))); //$NON-NLS-1$
		summary.add(allBook = new JLabel("")); //$NON-NLS-1$
		summary.add(new JLabel(MainWindow.getString("AccountListView.totalAvail"))); //$NON-NLS-1$
		summary.add(allAvailable = new JLabel("")); //$NON-NLS-1$
		data.add(summary, BorderLayout.SOUTH);

		final JPanel contentPane = (JPanel) getContentPane();
		contentPane.setBorder(BorderFactory.createEmptyBorder());
		contentPane.setLayout(new BorderLayout());
		contentPane.add(general, BorderLayout.NORTH);
		contentPane.add(buttons, BorderLayout.SOUTH);
		contentPane.add(data, BorderLayout.CENTER);

		GUIContext.getInstance().addContextListener(this);
	}

	public void showIt( final Customer customer, final Account[] list )
	{
		if ( list.length == 0 )
			return;

		this.customer = customer;
		this.accountsList = list;

		if ( customer == null )
		{
			bank.setText(MainWindow.getString("AccountListView.multiple")); //$NON-NLS-1$
			customerName.setText(""); //$NON-NLS-1$
		}
		else
		{
			bank.setText(customer.getBank().getName());
			customerName.setText(customer.getName());
		}

		final AccountListModel model = new AccountListModel(list);
		accounts.setModel(model);

		Amount totalBook = new Amount(0, customer.getBank().getBaseCurrency());
		Amount totalAvailable = totalBook;
		try
		{
			for ( final Account account : list )
			{

				totalBook = totalBook.add(account.getBookedBalance());
				totalAvailable = totalAvailable.add(account.getAvailableBalance());
			}
			allBook.setText(String.valueOf(totalBook));
			allAvailable.setText(String.valueOf(totalAvailable));
		}
		catch ( final IllegalArgumentException e )
		{
			allBook.setText(MainWindow.getString("AccountListView.differentCurrencies")); //$NON-NLS-1$
			allAvailable.setText(MainWindow.getString("AccountListView.differentCurrencies")); //$NON-NLS-1$
		}
		setVisible(true);

		TableSizeContainer.getInstance().monitorTable("AccountListView.accounts", accounts); //$NON-NLS-1$
	}

	class AccountListModel extends AbstractTableModel
	{
		private final Account[] accounts;

		public AccountListModel( final Account[] list )
		{
			super();
			accounts = list;
		}

		public AccountListModel()
		{
			super();
			accounts = new Account[0];
		}

		@Override
		public int getColumnCount()
		{
			return HEADERS.length;
		}

		@Override
		public int getRowCount()
		{
			return accounts.length;
		}

		@Override
		public Class<?> getColumnClass( final int columnIndex )
		{
			return COLUMN_CLASS[columnIndex];
		}

		@Override
		public Object getValueAt( final int rowIndex, final int columnIndex )
		{
			final Account account = accounts[rowIndex];
			Object result = null;
			switch ( columnIndex )
			{
			case 0:
				final URL icon = account.getBank().getSmallIcon();
				if ( icon != null )
					result = GUIContext.getIcon(icon);
				break;
			case 1:
				result = account.getNumber();
				break;
			case 2:
				result = account.getName();
				break;
			case 3:
				result = account.getType();
				break;
			case 4:
				result = account.getCurrency();
				break;
			case 5:
				result = account.getBookedBalance();
				break;
			case 6:
				result = account.getAvailableBalance();
				break;
			}
			return result;
		}

		public Account getAccountAt( final int row )
		{
			return accounts[row];
		}

		@Override
		public boolean isCellEditable( final int rowIndex, final int columnIndex )
		{
			// this is a read only model
			return false;
		}

		@Override
		public String getColumnName( final int column )
		{
			return HEADERS[column];
		}

	}

	@Override
	public void contextEventPerformed( final int eventType )
	{
		if ( customer != null )
		{
			if ( eventType == SESSION_REMOVED )
			{
				final List<Session> sessions = GUIContext.getInstance().getSessions();
				boolean sessionStillActive = false;
				for ( final Session session : sessions )
				{
					if ( session.getCustomer() == customer )
					{
						sessionStillActive = true;
						break;
					}
				}
				if ( !sessionStillActive )
				{
					dispose();
				}
			}
		}
		else
		{
			if ( GUIContext.getInstance().hasActiveSession() )
			{
				( (AccountOverviewAction) ActionFactory.getAction(AccountOverviewAction.class) ).updateView(this);
			}
			else
			{
				dispose();
			}
		}

	}

}
